import { DataGridColumn, DataGridProps } from '../../data-grid.props';
import FTransfer from '../../../../transfer/src/transfer.component';
import FTabs from '../../../../tabs/src/tabs.component';
import FTabPage from '../../../../tabs/src/components/tab-page.component';
import FOrder from '../../../../order/src/order.component';
import FConditionList from '../../../../condition/src/condition-list.component';
import { App, Ref, computed, nextTick, ref } from 'vue';
import { UseColumn, UseDataView, UseFilter, UseFitColumn, UseSort, UseVirtualScroll } from '../../composition/types';
import { OrderedItem, SortType } from '../../../../order';
import { EditorConfig } from '../../../../dynamic-form';
import { Condition, FieldConfig } from '../../../../condition/src/types';
import { ConditionValue } from '../../../../condition/src/composition/condition-value/types';

export default function (
    props: DataGridProps,
    gridContentRef: Ref<any>,
    viewPortWidth: Ref<number>,
    useColumnComposition: UseColumn,
    useDataViewComposition: UseDataView,
    useFilterComposition: UseFilter,
    useFitColumnComposition: UseFitColumn,
    useSorterComposition: UseSort,
    useVirtualScrollComposition: UseVirtualScroll
) {
    const identifyField = 'id';
    const conditionListRef = ref<any>();
    const {
        applySortableColumns,
        collectionFilterableColumns,
        collectionSortableColumns,
        columnContext,
        updateColumnSettingIcon: resetSettingIconPosition
    } = useColumnComposition;
    const { conditions } = useFilterComposition;
    const { calculateColumnsSize: resetVisibleColumnPosition } = useFitColumnComposition;
    const { fitHorizontalScroll: resetHorizontalScrollPosition } = useVirtualScrollComposition;
    const orderedResult = ref<OrderedItem[]>([]);
    const shouldApplyOrderedResult = computed(() => !!orderedResult.value.length);
    const dataSoruce = computed(() => {
        return columnContext.value.primaryColumns.map((dataGridColumn: DataGridColumn) => ({
            id: dataGridColumn.field,
            name: dataGridColumn.title
        }));
    });

    const visibleColumns = computed(() => {
        return columnContext.value.primaryColumns
            .filter((dataGridColumn: DataGridColumn) => dataGridColumn.visible)
            .map((visibleColumn: DataGridColumn) => ({
                id: visibleColumn.field,
                name: visibleColumn.title
            }));
    });

    const sortedColumns = computed<OrderedItem[]>(() => {
        return collectionSortableColumns().map((sortedColumn: DataGridColumn) => ({
            id: sortedColumn.field,
            name: sortedColumn.title,
            order: sortedColumn.sort as SortType
        }));
    });

    const filterableColumns = computed<FieldConfig[]>(() => {
        return collectionFilterableColumns().map((filterableColumn: DataGridColumn) => ({
            id: filterableColumn.field,
            code: filterableColumn.field,
            labelCode: filterableColumn.field,
            name: filterableColumn.title,
            editor: filterableColumn.editor || ({ type: useFilterComposition.getFilterEditorType(filterableColumn) } as EditorConfig),
            value: {} as ConditionValue,
            visible: true
        }));
    });

    function onCloseSettingPanel(app: App) {
        if (app) {
            app.unmount();
        }
    }

    function resetVisibleColumns() {
        const dataGridColumnMap = new Map<string, DataGridColumn>();
        columnContext.value.primaryColumns.reduce((columnMap: Map<string, DataGridColumn>, column: DataGridColumn) => {
            column.visible = false;
            columnMap.set(column.field, column);
            return columnMap;
        }, dataGridColumnMap);
        return dataGridColumnMap;
    }

    function applyVisibleStatus(visibleStatus: { id: string; name: string }[], dataGridColumnMap: Map<string, DataGridColumn>) {
        const latestOrderedVisibleColumns = visibleStatus.map(({ id: field }) => {
            const column = dataGridColumnMap.get(field) as DataGridColumn;
            column.visible = true;
            dataGridColumnMap.delete(field);
            return column;
        });
        return latestOrderedVisibleColumns;
    }

    function onVisibleColumnsChange(visibleStatus: { id: string; name: string }[]) {
        const dataGridColumnMap = resetVisibleColumns();
        const latestOrderedVisibleColumns = applyVisibleStatus(visibleStatus, dataGridColumnMap);
        columnContext.value.primaryColumns = [...latestOrderedVisibleColumns, ...Array.from(dataGridColumnMap.values())];
        resetSettingIconPosition();
        resetVisibleColumnPosition(columnContext, gridContentRef.value, viewPortWidth);
        nextTick(() => {
            resetHorizontalScrollPosition();
        });
    }

    function onSortedColumnsChange(ordereditems: OrderedItem[]) {
        orderedResult.value = ordereditems;
    }

    function renderSettingsPanel(app: App) {
        return (
            <div class="fv-grid-settings">
                <FTabs tab-type="pills" justify-content="center">
                    {{
                        headerPrefix: () => (
                            <div class="modal-title">
                                <span class="modal-title-label">列配置</span>
                            </div>
                        ),
                        default: () => [
                            <FTabPage id="display-columns" title="显示列" class="container">
                                <FTransfer
                                    style="height: 480px"
                                    identify-field={identifyField}
                                    data-source={dataSoruce.value}
                                    selections={visibleColumns.value}
                                    onChange={onVisibleColumnsChange}></FTransfer>
                            </FTabPage>,
                            <FTabPage id="column-order" title="列排序" class="container">
                                <FOrder
                                    style="height: 480px"
                                    data-source={dataSoruce.value}
                                    items={sortedColumns.value}
                                    onChange={onSortedColumnsChange}></FOrder>
                            </FTabPage>,
                            <FTabPage id="column-filter" title="筛选" class="container">
                                <FConditionList
                                    ref={conditionListRef}
                                    style="height: 480px"
                                    fields={filterableColumns.value}
                                    conditions={conditions.value}></FConditionList>
                            </FTabPage>
                            // <FTabPage id="groups" title="分组" class="container">
                            //     Content of Column Group
                            // </FTabPage>,
                            // <FTabPage id="grid-setting" title="表格配置" class="container">
                            //     Content of Grid Setting
                            // </FTabPage>
                        ],
                        headerSuffix: () => (
                            <div class="f-btn-icon f-bare" onClick={(payload: MouseEvent) => onCloseSettingPanel(app)}>
                                <span class="f-icon modal_close"></span>
                            </div>
                        )
                    }}
                </FTabs>
            </div>
        );
    }

    function resetSortableColumns() {
        const sortableColumnMap = new Map<string, DataGridColumn>();
        collectionSortableColumns().reduce((columnMap: Map<string, DataGridColumn>, sortableColumn: DataGridColumn) => {
            sortableColumn.sort = 'none';
            sortableColumn.sortOrder = 0;
            columnMap.set(sortableColumn.field, sortableColumn);
            return columnMap;
        }, sortableColumnMap);
        return sortableColumnMap;
    }

    function applySortResult(sortableColumnMap: Map<string, DataGridColumn>) {
        const sortableColumns = orderedResult.value
            .filter((item: OrderedItem) => item.id && item.order)
            .map((orderedItem: OrderedItem, index: number) => {
                const sortOrder = index + 1;
                const sortableColumn = sortableColumnMap.get(orderedItem.id) as DataGridColumn;
                if (sortableColumn) {
                    sortableColumn.sort = orderedItem.order;
                    sortableColumn.sortOrder = sortOrder;
                }
                return sortableColumn;
            });
        return sortableColumns;
    }

    function applyOrderResult() {
        if (shouldApplyOrderedResult.value) {
            const sortableColumnMap = resetSortableColumns();
            const sortableColumns = applySortResult(sortableColumnMap);
            applySortableColumns(sortableColumns, useDataViewComposition, useSorterComposition);
            useVirtualScrollComposition.reCalculateVisualDataRows();
            resetVisibleColumnPosition(columnContext, gridContentRef.value, viewPortWidth);
        }
    }

    function applyFilterResult() {
        if (conditionListRef.value) {
            conditions.value = conditionListRef.value.getConditions() as Condition[];
            useDataViewComposition.refresh();
            useVirtualScrollComposition.reCalculateVisualDataRows();
        }
    }

    function acceptCallback() {
        applyOrderResult();
        applyFilterResult();
    }

    function rejectCallback() {}

    return { acceptCallback, rejectCallback, renderSettingsPanel };
}
